#pragma once
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/async.h>
#include <iostream>

////////////////////////////////////////////////////////////////
/// @file logger.hpp
/// @brief 基于spdlog的日志系统封装
/// @details 提供简化的日志接口，支持控制台和文件两种输出模式
///          - 开发模式：彩色控制台输出，记录所有级别日志
///          - 发布模式：文件输出，可配置日志级别
/// @author quan
/// @date 2025-10-10
////////////////////////////////////////////////////////////////

/// @brief 全局默认日志器
/// @details 在init_default_logger()中初始化，之后通过宏进行访问
///          使用shared_ptr管理生命周期，确保程序退出时正确析构
std::shared_ptr<spdlog::logger> default_logger;

/// @brief 初始化全局日志器
/// @param is_release 是否为发布模式
///                   - false: 开发模式，输出到彩色控制台，记录所有日志
///                   - true:  发布模式，输出到文件，按指定级别记录
/// @param file 日志文件路径（仅发布模式有效），如："logs/app.log"
/// @param level 日志级别（仅发布模式有效），取值范围：
///              - 0: trace    - 最详细的跟踪信息
///              - 1: debug    - 调试信息
///              - 2: info     - 一般信息
///              - 3: warn     - 警告信息
///              - 4: error    - 错误信息
///              - 5: critical - 严重错误
/// @note 
///   - 必须在使用日志宏之前调用此函数
///   - 开发模式下level参数被忽略，始终记录trace级别
///   - 日志格式：[时间] [级别] [进程ID:线程ID] [文件:行号] 消息
/// @warning 重复调用会创建新的logger实例，建议只在程序启动时调用一次
/// 
/// @par 使用示例：
/// @code
/// // 开发模式
/// init_default_logger(false, "", 0);
/// 
/// // 发布模式，输出到文件，只记录info及以上级别
/// init_default_logger(true, "logs/server.log", 2);
/// @endcode
void init_default_logger(bool is_release, const std::string& file, int32_t level)
{
    if(!is_release)
    {
        default_logger = spdlog::stdout_color_mt("default_logger");
        default_logger->set_level(spdlog::level::level_enum::trace);
        default_logger->flush_on(spdlog::level::level_enum::trace);
    }
    else
    {
        default_logger = spdlog::basic_logger_mt("default_logger", file);
        default_logger->set_level((spdlog::level::level_enum)level);
        default_logger->flush_on((spdlog::level::level_enum)level);
    }
    default_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%F] [%-8l] [%P:%t] %v");
}


#define strace(fmt, ...) default_logger->trace   (std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define sdebug(fmt, ...) default_logger->debug   (std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define sinfo( fmt, ...) default_logger->info    (std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define swarn( fmt, ...) default_logger->warn    (std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define serror(fmt, ...) default_logger->error   (std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define sfatal(fmt, ...) default_logger->critical(std::string("[{}:{}] ") + fmt, __FILE__, __LINE__, ##__VA_ARGS__)